package org.agent.aigccore.basic.security;

import org.agent.aigccore.core.service.user.UserService;
import org.agent.aigccore.model.po.UserInfoPO;
import org.agent.aigccore.utils.JwtUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import jakarta.annotation.Resource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
    
    @Resource
    private JwtUtil jwtUtil;
    
    @Resource
    private UserService userService;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        
        logger.info("开始JWT认证过滤");
        final String requestTokenHeader = request.getHeader("Authorization");
        logger.info("请求头Authorization: {}", requestTokenHeader);
        
        String username = null;
        String jwtToken = null;
        
        // JWT Token is in the form "Bearer token". Remove Bearer word and get only the Token
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            logger.info("提取JWT Token: {}", jwtToken);
            try {
                username = jwtUtil.getUsernameFromToken(jwtToken);
                logger.info("从Token中提取用户名: {}", username);
            } catch (IllegalArgumentException e) {
                logger.error("无法获取JWT Token", e);
            } catch (Exception e) {
                logger.error("JWT Token已过期", e);
            }
        } else {
            logger.info("请求头中没有有效的Bearer Token");
        }
        
        // Once we get the token validate it.
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            logger.info("开始验证Token");
            
            try {
                UserInfoPO userInfoPO = this.userService.loadByUsername(username);
                logger.info("根据用户名查询到的用户信息: {}", userInfoPO);
                
                if (userInfoPO == null) {
                    logger.warn("未找到用户名为{}的用户", username);
                }
                
                // if token is valid configure Spring Security to manually set authentication
                if (jwtUtil.validateToken(jwtToken, userInfoPO)) {
                    logger.info("Token验证成功");
                    // 修复权限设置问题
                    List<SimpleGrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + userInfoPO.getRole()));
                    logger.info("用户权限: {}", authorities);
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userInfoPO, null, authorities);
                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // After setting the Authentication in the context, we specify
                    // that the current user is authenticated. So it passes the Spring Security Configurations successfully.
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    logger.info("设置认证信息成功");
                } else {
                    logger.warn("Token验证失败");
                }
            } catch (Exception e) {
                logger.error("验证Token时发生错误", e);
            }
        } else {
            if (username == null) {
                logger.info("用户名为空，跳过Token验证");
            } else {
                logger.info("Security上下文中已有认证信息，跳过Token验证");
            }
        }
        chain.doFilter(request, response);
        logger.info("JWT认证过滤完成");
    }
}